﻿using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Configuration;
using Donal.Xms.Common;
using Donal.Xms.API.OAuth;
using System.Linq;

namespace Donal.Xms.Web.UI
{
    public partial class BasePage : System.Web.UI.Page
    {
        public Model.sysconfig config = new BLL.sysconfig().loadConfig();
        public Model.userconfig uconfig = new BLL.userconfig().loadConfig();
        public Model.sites site = new Model.sites();

        /// <summary>
        /// 父类的构造函数
        /// </summary>
        public BasePage()
        {
            //是否关闭网站
            if (config.webstatus == 0)
            {
                HttpContext.Current.Response.Redirect(linkurl(0, "error", "?msg=" + Utils.UrlEncode(config.webclosereason)));
                return;
            }
            //取得站点信息
            site = GetSiteModel();
            //抛出一个虚方法给继承重写
            ShowPage();
        }

        /// <summary>
        /// 页面处理虚方法
        /// </summary>
        protected virtual void ShowPage()
        {
            //虚方法代码
        }

        #region 判断是否为移动端
        public bool isMobile()
        {
            string u = HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"];
            if (u == null)
            {
                return false;
            }
            Regex b = new Regex(@"android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            Regex v = new Regex(@"1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            if (!(b.IsMatch(u) || v.IsMatch(u.Substring(0, 4))))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        #endregion

        /// <summary>
        /// 基类加载完后验证是否为微信公众号登录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Base_Init(object sender, EventArgs e)
        {
            string url = "http://" + HttpContext.Current.Request.Url.Authority.ToLower() + HttpContext.Current.Request.RawUrl;

            if (url.IndexOf("Query=weixin") > 0)
            {
                if (!IsUserLogin())
                {
                    Utils.WriteCookie(DTKeys.COOKIE_URL_REFERRER, url.Replace("?Query=weixin", ""));

                    //获得配置信息
                    oauth_config oauth_config = oauth_helper.get_config(4);
                    if (oauth_config == null)
                    {
                        HttpContext.Current.Response.Redirect(linkurl(0, "error", "?msg=出错了，您尚未配置微信的API信息！"));
                        return;
                    }
                    string state = Guid.NewGuid().ToString().Replace("-", "");

                    string send_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + oauth_config.oauth_app_id
                        + "&redirect_uri=" + Utils.UrlEncode("http://" + HttpContext.Current.Request.Url.Authority.ToLower() + "/api/oauth/weixin/return_uri.aspx")
                        + "&response_type=code&scope=snsapi_userinfo&state=" + state + "#wechat_redirect";

                    //开始发送
                    HttpContext.Current.Response.Redirect(send_url);
                }
            }
        }


        #region 页面通用方法==========================================
        /// <summary>
        /// 返回站点信息
        /// </summary>
        protected Model.sites GetSiteModel()
        {
            string requestDomain = HttpContext.Current.Request.Url.Authority.ToLower(); //获得来源域名含端口号
            string requestPath = HttpContext.Current.Request.RawUrl.ToLower(); //当前的URL地址
            string sitePath = GetSitePath(requestPath, requestDomain);
            Model.sites modelt = SiteDomains.GetSiteDomains().SiteList.Find(p => p.build_path == sitePath);
            return modelt;
        }

        /// <summary>
        /// 返回URL重写统一链接地址
        /// </summary>     
        /// <param name="_key">关键字，必填</param>
        /// <param name="_params">参数列表</param>
        public string linkurl(string _key, params object[] _params)
        {
            return linkurl(0, _key, _params);
        }

        /// <summary>
        /// 返回URL重写统一链接地址
        /// </summary>
        /// <param name="pageCount">生成静态时，当页面有列表时，输入大于0的页面总数。在后台生成静态时，才会用到的参数，其它情况无效。</param>
        /// <param name="_key">关键字，必填</param>
        /// <param name="_params">参数列表</param>
        public string linkurl(int pageCount, string _key, params object[] _params)
        {
            Hashtable ht = new BLL.url_rewrite().GetList(); //获得URL配置列表
            Model.url_rewrite model = ht[_key] as Model.url_rewrite; //查找指定的URL配置节点

            //如果不存在该节点则返回空字符串
            if (model == null)
            {
                return string.Empty;
            }

            string requestDomain = HttpContext.Current.Request.Url.Authority.ToLower(); //获得来源域名含端口号
            string requestPath = HttpContext.Current.Request.RawUrl.ToLower(); //当前的URL地址
            string linkStartString = GetLinkStartString(requestPath, requestDomain); //链接前缀
            string sitePath = GetSitePath(config.webpath, requestPath, requestDomain);

            //如果URL字典表达式不需要重写则直接返回
            if (model.url_rewrite_items.Count == 0)
            {
                //检查网站重写状态
                if (config.staticstatus > 0)
                {
                    if (_params.Length > 0)
                    {
                        return linkStartString + GetUrlExtension(model.page, config.staticextension) + string.Format("{0}", _params);
                    }
                    else
                    {
                        return linkStartString + GetUrlExtension(model.page, config.staticextension);
                    }
                }
                else
                {
                    if (_params.Length > 0)
                    {
                        return linkStartString + model.page + string.Format("{0}", _params);
                    }
                    else
                    {
                        return linkStartString + model.page;
                    }
                }
            }


            //否则检查该URL配置节点下的子节点
            foreach (Model.url_rewrite_item item in model.url_rewrite_items)
            {
                //如果参数个数匹配
                if (IsUrlMatch(item, _params))
                {
                    if (config.isBuilding)
                    {
                        string aspx_filename = string.Format("{0}{1}/{2}/{3}", config.webpath, DTKeys.DIRECTORY_REWRITE_ASPX, sitePath, model.page + get_params(_params, item.querystring));
                        string catalogue = (config.HtmlsPath != DTKeys.DIRECTORY_REWRITE_HTML_LEFT ? DTKeys.DIRECTORY_REWRITE_HTML_LEFT : DTKeys.DIRECTORY_REWRITE_HTML_RIGHT)
                            + linkStartString + (linkStartString.EndsWith("/") ? "" : "/") + sitePath + "/" + string.Format(GetUrlExtension(item.path, config.staticextension), _params);
                        string dic_item = "";

                        if (aspx_filename.Contains("__id__"))
                        {
                            for (int i = 1; i <= pageCount; i++)
                            {
                                dic_item = sitePath + "&aspx_filename=" + aspx_filename.Replace("__id__", i.ToString()) + "&catalogue=" + catalogue.Replace("__id__", i.ToString());

                                if (!Donal.Xms.Common.Utils.dic_web_path.ContainsKey(dic_item))
                                {
                                    try { Donal.Xms.Common.Utils.dic_web_path.Add(dic_item, 0); } catch { }

                                }
                            }
                        }
                        else
                        {
                            dic_item = sitePath + "&aspx_filename=" + aspx_filename + "&catalogue=" + catalogue;

                            if (!Donal.Xms.Common.Utils.dic_web_path.ContainsKey(dic_item))
                            {
                                try { Donal.Xms.Common.Utils.dic_web_path.Add(dic_item, 0); } catch { }
                            }
                        }
                    }

                    //检查网站重写状态
                    if (config.staticstatus > 0)
                    {
                        string request_url = linkStartString + string.Format(GetUrlExtension(item.path, config.staticextension), _params);
                        return request_url;
                    }
                    else
                    {
                        string queryString = Regex.Replace(string.Format(item.path, _params), item.pattern, item.querystring, RegexOptions.None | RegexOptions.IgnoreCase);
                        if (queryString.Length > 0)
                        {
                            queryString = "?" + queryString;
                        }
                        return linkStartString + model.page + queryString;
                    }
                }
            }

            return string.Empty;
        }

        private string get_params(object[] _params, string querystring)
        {
            if (_params.Length > 0)
            {
                for (int i = 0; i < _params.Length; i++)
                {
                    querystring = querystring.Replace("$" + (i + 1), _params[i].ToString());
                }

                return "?" + querystring.Replace("^", "&") + "&isbuilding=1";
            }

            return "?isbuilding=1";
        }

        /// <summary>
        /// 获取站点的目录
        /// </summary>
        /// <param name="webPath">网站安装目录</param>
        /// <param name="requestPath">获取的页面，包含目录</param>
        /// <param name="requestDomain">获取的域名(含端口号)</param>
        /// <returns>String</returns>
        private string GetSitePath(string webPath, string requestPath, string requestDomain)
        {
            //获取当前域名包含的站点目录
            string domainPath = GetCurrDomainPath(requestDomain);
            if (domainPath != string.Empty)
            {
                return domainPath;
            }
            // 获取当前页面包含的站点目录
            string pagePath = GetCurrPagePath(webPath, requestPath);
            if (pagePath != string.Empty)
            {
                return pagePath;
            }
            return SiteDomains.GetSiteDomains().DefaultPath;
        }

        /// <summary>
        /// 获取当前域名包含的站点目录
        /// </summary>
        /// <param name="requestDomain">获取的域名(含端口号)</param>
        /// <returns>String</returns>
        private string GetCurrDomainPath(string requestDomain)
        {
            //当前域名是否存在于站点目录列表
            if (SiteDomains.GetSiteDomains().Paths.ContainsValue(requestDomain))
            {
                string sitePath = SiteDomains.GetSiteDomains().Domains[requestDomain];
                //如果存在，检查是否默认站点，是则还需检查虚拟目录部分
                if (sitePath != SiteDomains.GetSiteDomains().DefaultPath)
                {
                    return sitePath;
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// 获取当前页面包含的站点目录
        /// </summary>
        /// <param name="webPath">网站安装目录</param>
        /// <param name="requestPath">获取的页面，包含目录</param>
        /// <returns>String</returns>
        private string GetCurrPagePath(string webPath, string requestPath)
        {
            //获取URL的虚拟目录(除安装目录)
            string requestFirstPath = GetFirstPath(webPath, requestPath);
            if (requestFirstPath != string.Empty && SiteDomains.GetSiteDomains().Paths.ContainsKey(requestFirstPath))
            {
                return requestFirstPath;
            }
            return string.Empty;
        }

        /// <summary>
        /// 获取URL的虚拟目录(除安装目录)
        /// </summary>
        /// <param name="webPath">网站安装目录</param>
        /// <param name="requestPath">当前页面，包含目录</param>
        /// <returns>String</returns>
        private string GetFirstPath(string webPath, string requestPath)
        {
            if (requestPath.StartsWith(webPath))
            {
                string tempStr = requestPath.Substring(webPath.Length);
                if (tempStr.IndexOf("/") > 0)
                {
                    return tempStr.Substring(0, tempStr.IndexOf("/")).ToLower();
                }
            }
            return string.Empty;
        }


        /// <summary>
        /// 根据站点目录和已生成的链接重新组合(实际访问页面用到)
        /// </summary>
        /// <param name="sitepath">站点目录</param>
        /// <param name="urlpath">URL链接</param>
        /// <returns>String</returns>
        public string getlink(string sitepath, string urlpath)
        {
            if (string.IsNullOrEmpty(sitepath) || string.IsNullOrEmpty(urlpath))
            {
                return urlpath;
            }
            string requestDomain = HttpContext.Current.Request.Url.Authority.ToLower(); //获取来源域名含端口号
            Dictionary<string, string> dic = SiteDomains.GetSiteDomains().Paths; //获取站点键值对
            //如果当前站点为默认站点则直接返回
            if (SiteDomains.GetSiteDomains().DefaultPath == sitepath.ToLower())
            {
                return urlpath;
            }
            //如果当前域名存在于域名列表则直接返回
            if (dic.ContainsKey(sitepath.ToLower()) && dic.ContainsValue(requestDomain))
            {
                return urlpath;
            }
            int indexNum = config.webpath.Length; //安装目录长度
            if (urlpath.StartsWith(config.webpath))
            {
                urlpath = urlpath.Substring(indexNum);
            }
            //安装目录+站点目录+URL
            return config.webpath + sitepath.ToLower() + "/" + urlpath;
        }

        /// <summary>
        /// 返回分页字符串
        /// </summary>
        /// <param name="pagesize">页面大小</param>
        /// <param name="pageindex">当前页</param>
        /// <param name="totalcount">记录总数</param>
        /// <param name="_key">URL映射Name名称</param>
        /// <param name="_params">传输参数</param>
        protected string get_page_link(int pagesize, int pageindex, int totalcount, string _key, params object[] _params)
        {
            return Utils.OutPageList(pagesize, pageindex, totalcount, linkurl(0, _key, _params), 8);
        }

        /// <summary>
        /// 返回分页字符串
        /// </summary>
        /// <param name="pagesize">页面大小</param>
        /// <param name="pageindex">当前页</param>
        /// <param name="totalcount">记录总数</param>
        /// <param name="linkurl">链接地址</param>
        protected string get_page_link(int pagesize, int pageindex, int totalcount, string linkurl)
        {
            return Utils.OutPageList(pagesize, pageindex, totalcount, linkurl, 8);
        }
        #endregion

        #region 会员用户方法==========================================
        /// <summary>
        /// 判断用户是否已经登录(解决Session超时问题)
        /// </summary>
        public bool IsUserLogin()
        {
            if (HttpContext.Current.Session[DTKeys.SESSION_USER_INFO] is Model.users model)
            {
                Utils.WriteCookie(DTKeys.COOKIE_USER_NAME_REMEMBER, "Donal.Xms.UserName",
                    DESEncrypt.Encrypt(DateTime.Now.ToString("yyyy-MM-dd HH:mm") + "_" + DESEncrypt.Encrypt(model.user_name)), 43200);//30天
                Utils.WriteCookie(DTKeys.COOKIE_USER_PWD_REMEMBER, "Donal.Xms.PassWord",
                    DESEncrypt.Encrypt(DateTime.Now.ToString("yyyy-MM-dd HH:mm") + "_" + model.password), 43200);
                return true;
            }
            else
            {
                //检查Cookies
                string username = Utils.GetCookie(DTKeys.COOKIE_USER_NAME_REMEMBER, "Donal.Xms.UserName");
                string password = Utils.GetCookie(DTKeys.COOKIE_USER_PWD_REMEMBER, "Donal.Xms.PassWord");
                if (username != "" && password != "")
                {
                    username = DESEncrypt.Decrypt(username);
                    if (username != "" && username.Split('_').Length == 2)
                    {
                        DateTime dt = Utils.ObjectToDateTime(username.Split('_')[0], DateTime.Now.AddDays(-30));
                        if (dt <= DateTime.Now.AddDays(-30))
                        {
                            return false;
                        }
                        username = DESEncrypt.Decrypt(username.Split('_')[1]);
                    }

                    password = DESEncrypt.Decrypt(password);
                    if (password != "" && password.Split('_').Length == 2)
                    {
                        DateTime dt = Utils.ObjectToDateTime(password.Split('_')[0], DateTime.Now.AddDays(-30));
                        if (dt <= DateTime.Now.AddDays(-30))
                        {
                            return false;
                        }
                        password = password.Split('_')[1];
                    }

                    model = new BLL.users().GetModel(username, password, 0, 0, false);
                    if (model != null)
                    {
                        HttpContext.Current.Session[DTKeys.SESSION_USER_INFO] = model;
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 取得用户信息
        /// </summary>
        /// <param name="news">默认false获取Seeion中的信息，为true时，获取最新信息。</param>
        public Model.users GetUserInfo()
        {
            if (IsUserLogin())
            {
                return HttpContext.Current.Session[DTKeys.SESSION_USER_INFO] as Model.users;
            }
            return null;
        }

        #endregion

        #region 辅助方法(私有)========================================
        /// <summary>
        /// 获取当前页面包含的站点目录
        /// </summary>
        private string GetFirstPath(string requestPath)
        {
            int indexNum = config.webpath.Length; //安装目录长度
            //如果包含安装目录和aspx目录也要过滤掉
            if (requestPath.StartsWith(config.webpath + DTKeys.DIRECTORY_REWRITE_ASPX + "/"))
            {
                indexNum = (config.webpath + DTKeys.DIRECTORY_REWRITE_ASPX + "/").Length;
            }
            string requestFirstPath = requestPath.Substring(indexNum);
            if (requestFirstPath.IndexOf("/") > 0)
            {
                requestFirstPath = requestFirstPath.Substring(0, requestFirstPath.IndexOf("/"));
            }
            if (requestFirstPath != string.Empty && SiteDomains.GetSiteDomains().Paths.ContainsKey(requestFirstPath))
            {
                return requestFirstPath;
            }
            return string.Empty;
        }

        /// <summary>
        /// 获取链接的前缀
        /// </summary>
        /// <param name="requestPath">当前的URL地址</param>
        /// <param name="requestDomain">获得来源域名含端口号</param>
        /// <returns>String</returns>
        private string GetLinkStartString(string requestPath, string requestDomain)
        {
            string requestFirstPath = GetFirstPath(requestPath);//获得二级目录(不含站点安装目录)

            //检查是否与绑定的域名或者与默认站点的目录匹配
            if (SiteDomains.GetSiteDomains().Paths.ContainsValue(requestDomain))
            {
                return "/";
            }
            else if (requestFirstPath == string.Empty || requestFirstPath == SiteDomains.GetSiteDomains().DefaultPath)
            {
                return config.webpath;
            }
            else
            {
                return config.webpath + requestFirstPath + "/";
            }
        }

        /// <summary>
        /// 获取站点的目录
        /// </summary>
        /// <param name="requestPath">获取的页面，包含目录</param>
        /// <param name="requestDomain">获取的域名(含端口号)</param>
        /// <returns>String</returns>
        private string GetSitePath(string requestPath, string requestDomain)
        {
            //当前域名是否存在于站点目录列表
            if (SiteDomains.GetSiteDomains().Paths.ContainsValue(requestDomain))
            {
                return SiteDomains.GetSiteDomains().Domains[requestDomain];
            }

            // 获取当前页面包含的站点目录
            string pagePath = GetFirstPath(requestPath);
            if (pagePath != string.Empty)
            {
                return pagePath;
            }
            return SiteDomains.GetSiteDomains().DefaultPath;
        }

        /// <summary>
        /// 参数个数是否匹配
        /// </summary>
        private bool IsUrlMatch(Model.url_rewrite_item item, params object[] _params)
        {
            int strLength = 0;
            if (!string.IsNullOrEmpty(item.querystring))
            {
                strLength = item.querystring.Split('&').Length;
            }
            if (strLength == _params.Length)
            {
                //注意__id__代表分页页码，所以须替换成数字才成进行匹配
                if (Regex.IsMatch(string.Format(item.path, _params).Replace("__id__", "1"), item.pattern, RegexOptions.None | RegexOptions.IgnoreCase))
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 替换扩展名
        /// </summary>
        private string GetUrlExtension(string urlPage, string staticExtension)
        {
            return Utils.GetUrlExtension(urlPage, staticExtension);
        }

        /// <summary>
        /// 返回微信配置信息
        /// </summary>
        public oauth_config GetOauthConfig()
        {
            oauth_config _config = CacheHelper.Get<oauth_config>(DTKeys.CACHE_WEIXIN_CONFIG_RUNTIME);
            if (_config == null)
            {
                CacheHelper.Insert(DTKeys.CACHE_WEIXIN_CONFIG_RUNTIME, oauth_helper.get_config(1), 60);
                return CacheHelper.Get<oauth_config>(DTKeys.CACHE_WEIXIN_CONFIG_RUNTIME);
            }
            return _config;
        }

        #endregion
    }
}
